﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TaskFrame
{
    /// <summary>
    /// 任务管理器
    /// </summary>
    public class TaskManager
    {
        /// <summary>
        /// 是否正在运行
        /// </summary>
        public bool IsRuning { get; set; }

        /// <summary>
        /// 运行的线程
        /// </summary>
        private Thread thread;

        private AutoResetEvent ResetEvent = new AutoResetEvent(false);

        /// <summary>
        /// 现在的时间点
        /// </summary>
        public static long TimeNow { get { return (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; } }

        private List<WatcherTask> _TaskList = new List<WatcherTask>();

        private TaskManager() { }

        private static TaskManager _TaskManager = new TaskManager();

        public static TaskManager GetInstance() { return _TaskManager; }

        private void AdjustNextRuntime()
        {
            lock (_TaskList)
            {
                Sort();

                // 延时等待执行
                NextRunTime = TimeNow + 1000 * 60 * 10;

                if (_TaskList.Count > 0)
                {
                    lock (_TaskList)
                    {
                        if (_TaskList.Count > 0)
                        {
                            Sort();

                            NextRunTime = _TaskList.First().NextRunTime;
                        }
                    }
                }
            }
        }

        private void Sort()
        {
            lock (_TaskList)
            {
                _TaskList.Sort(delegate (WatcherTask t1, WatcherTask t2) { return (int)(t1.NextRunTime - t2.NextRunTime); });
            }
        }

        public void Add(WatcherTask task)
        {
            lock (_TaskList)
            {
                _TaskList.Add(task);
                AdjustNextRuntime();
                ResetEvent.Set();
            }
        }

        public void Remove(WatcherTask task)
        {
            lock (_TaskList)
            {
                _TaskList.Remove(task);
            }

            AdjustNextRuntime();
            ResetEvent.Set();
        }

        public void ClearWatcherTask()
        {
            lock (_TaskList)
            {
                _TaskList.Clear();
            }
        }

        /// <summary>
        /// 下次运行时间
        /// </summary>
        public long NextRunTime { get; protected set; } = 0;

        /// <summary>
        /// 启动
        /// </summary>
        public void Start()
        {
            IsRuning = true;
            thread = new Thread(() =>
            {
                int BusynessCount = 0;
                while (IsRuning)
                {
                    // 需要执行任务了
                    if (TimeNow >= NextRunTime)
                    {
                        List<WatcherTask> list = null;

                        lock (_TaskList)
                            list = new List<WatcherTask>(_TaskList);

                        List<Thread> thread_list = new List<Thread>();

                        foreach (var item in list)
                        {
                            if (TimeNow >= item.NextRunTime)
                            {
                                item.PreRun();
                                var thread = new Thread(() => { item.Run(); }) { IsBackground = true, Name = $"{item.Name} {item.Id}" };
                                thread_list.Add(thread);
                                thread.Start();
                                item.PostRun();
                            }
                            else
                            {
                                break;
                            }

                            if (!item.IsContinue)
                                Remove(item);
                        }

                        while (thread_list.Any(n => n.ThreadState != ThreadState.Stopped))
                            Thread.Sleep(10);
                    }

                    // 调整下次运行的事件
                    AdjustNextRuntime();

                    var wait_time = (int)Limit(NextRunTime - TimeNow, 0, 999999);

                    if (wait_time == 0)
                    {
                        BusynessCount = (BusynessCount + 1) % 10;
                    }
                    else
                    {
                        BusynessCount = 0;
                    }

                    ResetEvent.Reset();
                    ResetEvent.WaitOne(wait_time);
                }

                thread = null;
            });

            thread.Start();
        }

        /// <summary>
        /// 停止
        /// </summary>
        public void Stop()
        {
            IsRuning = false;

            ResetEvent.Set();

            while (thread != null)
                Thread.Sleep(100);
        }


        private static T Limit<T>(T v, T min, T max)
            where T : IComparable
        {
            if (v.CompareTo(min) < 0)
                return min;

            if (v.CompareTo(max) > 0)
                return max;

            return v;
        }
    }
}
